﻿module game.battle.enemies.missileboat;

import game.battle.enemies.base;
import game.battle.enemies.missile;

import game.battle.projectiles.enemyprojectiles;
import game.battle.projectiles.fireprojectiles;

import game.battle.weapons.baseweapon;

class MissileBoat : Base
{
private:
    Sprite mSprite;
    scalar_t mDir = 0;
    bool mAttack = false;
    int mHealth = 5;
    BaseWeapon!(100, cast(scalar_t)0, Missile,true) mLeftWeapon;
    BaseWeapon!(100, cast(scalar_t)0, Missile,true) mRightWeapon;
public:
    static immutable scalar_t acceleration = 1;
    static immutable scalar_t deceleration = acceleration / 2;
    static immutable scalar_t rotAcceleration = div(1,100);
    static immutable scalar_t rotDeceleration = rotAcceleration / 2;
    static immutable rot_t    rotAccelerationV = rot_t(cos(rotAcceleration), sin(rotAcceleration));
    static immutable rot_t    rotDecelerationV = rot_t(cos(rotDeceleration), sin(rotDeceleration));
    static immutable scalar_t maxRotSpeed = div(1,35);
    static immutable rot_t    maxRotSpeedV = rot_t(cos(maxRotSpeed), sin(maxRotSpeed));
    static immutable scalar_t maxSpeed = 6;
    static immutable maxSpeedSquared = maxSpeed * maxSpeed;
    
    static immutable scalarw_t radius = 12;
    static immutable radiusSq = radius * radius;
    
    static immutable scalarw_t maxRange = 1500;
    static immutable maxRangeSq = maxRange * maxRange;
    
    static immutable scalarw_t minRange = 600;
    static immutable minRangeSq = minRange * minRange;
    
    static immutable scalarw_t attackRange = 1000;
    static immutable attackRangeSq = attackRange * attackRange;
    
    @property auto health() const pure nothrow { return mHealth; }
    @property void health(int h) pure nothrow { mHealth = h; }
    
    @property bool up()    const pure nothrow { return true; }
    @property bool down()  const pure nothrow { return false; }
    @property bool left()  const pure nothrow { return mDir > 0; }
    @property bool right() const pure nothrow { return mDir < 0; }

    this(BattleScene w)
    {
        super(w);
        mSprite = w.textureManager.texture!"boat";
    }

    void updateAi() pure nothrow 
    {
        auto player = world.player;
        auto playerDir = (player.pos - pos);
        auto d1 = dot(dir, playerDir);
        if((d1 > 0) || playerDir.magnitude_squared > maxRangeSq)
        {
            mDir = wedge(dir, playerDir);
            if(playerDir.magnitude_squared < minRangeSq)
            {
                mDir = -mDir;
            }
        }
        else
        {
            mDir = 0;
        }
        
        mAttack = (playerDir.magnitude_squared < attackRangeSq) && (d1 > 0);
    }
    
    bool process()
    {
        update!true(this);
        mLeftWeapon.update();
        mRightWeapon.update();
        if(mHealth <= 0)
        {
            ExpandingFireProjectile proj;
            proj.pos = pos;
            proj.speed = speed;
            spawnProjectile(proj);
        }
        else if(mAttack)
        {
            auto offset = (dir * toRotMat(Pi2Rot)) * cast(scalar_t)10;
            mLeftWeapon.fire(this, pos + offset, speed, dir);
            mRightWeapon.fire(this, pos - offset, speed, dir);
        }
        return mHealth > 0;
    }
    
    void draw(Renderer ren, in TransformMapper mapper)
    {
        Point pt;
        double dr;
        if(mapper.map(pos, dir, pt, dr))
        {
            mSprite.draw(ren, pt, dr);
        }
    }
}